package main

import (
	"GoLandGOStudy/goStudy/foundationStudy/unitTwoDataType/enum"
	"fmt"
	"strconv"
	"unsafe"
)

// 全局变量：定义在函数外的变量
var n7 int = 100
var n8 float64 = 9.7

// 设计者认为上面的全局变量的写法太麻烦了，可以一次性声明：
var (
	n9  int    = 500
	n10 string = "netty"
)

func main() {
	fmt.Println(n7, n8, n9, n10)

	fmt.Println("枚举类--------------------------------------------------------")
	fmt.Println()
	types := enum.GoMessageType(6)
	is := types.IsValid()
	fmt.Println(is)

	fmt.Println()
	//变量和数据类型
	fmt.Println("整数数据类型--------------------------------------------------------")
	fmt.Println()

	// 定义整数类型
	var num int8 = 120
	fmt.Println("整数int8一个字节(-128-127) = ", num)

	var num1 uint8 = 20
	fmt.Println("整数uint8一个字节(0-255) = ", num1)

	// printf函数作用就是格式化，把num2的类型填充到%T的位置上
	var num2 = 28
	fmt.Printf("num2的类型是: %T", num2)
	fmt.Println()
	fmt.Println(unsafe.Sizeof(num2))
	fmt.Println()

	fmt.Println("浮点数据类型--------------------------------------------------------")
	fmt.Println()

	//定义浮点类型的数据：
	var sum1 float32 = 3.14
	fmt.Println("sum1 = ", sum1)

	// //可以表示正浮点数，也可以表示负的浮点数
	var sum2 float32 = 3.14
	fmt.Println("sum2 = ", sum2)

	// 浮点数可以用十进制表示形式，也可以用科学计数法表示形式  E 大写小写都可以的
	var sum3 float32 = 314e-2
	fmt.Println("sum3 = ", sum3)
	var sum4 float32 = 314e+2
	fmt.Println("sum4 = ", sum4)
	var sum5 float32 = 314e+2
	fmt.Println("sum5 = ", sum5)
	var sum6 float64 = 314e+2
	fmt.Println("sum6 = ", sum6)

	//浮点数可能会有精度的损失，所以通常情况下，建议你使用：float64
	var num7 float32 = 256.000000916
	fmt.Println("float32-num7 = ", num7)
	var num8 float64 = 256.000000916
	fmt.Println("float64-num8 = ", num8)

	//golang中默认的浮点类型为：float64
	var num9 = 3.17
	fmt.Printf("num9对应的默认的类型为: %T", num9)
	fmt.Println()

	fmt.Println("字符数据类型--------------------------------------------------------")
	fmt.Println()

	//定义字符类型的数据
	var c1 byte = '1'
	fmt.Println("字符类型c1 = ", c1) //49
	var c2 byte = 'a'
	fmt.Println("字符类型c2 = ", c2) //97
	var c3 byte = '('
	fmt.Println("字符类型c3 = ", c3) //40
	//字符类型，本质上就是一个整数，也可以直接参与运算，输出字符的时候，会将对应的码值做一个输出
	//字母，数字，标点等字符，底层是按照ASCII进行存储。

	var c4 int = '中'
	fmt.Println("字符类型c4", c4)
	//汉字字符，底层对应的是Unicode码值
	//对应的码值为20013，byte类型溢出，能存储的范围：可以用int
	//总结：Golang的字符对应的使用的是UTF-8编码（Unicode是对应的字符集，UTF-8是Unicode的其中的一种编码方案）

	var c5 byte = 'A'
	fmt.Printf("c5对应的具体字符为: %c", c5)
	fmt.Println()
	fmt.Println()

	fmt.Println("转义字符类型--------------------------------------------------------")

	// \n换行
	fmt.Println("换行 = aaa\nbbb")
	//\b 退格
	fmt.Println("退格 = aaa\bbbb")
	//\r 光标回到本行的开头，后续输入就会替换原有的字符
	fmt.Println("回车 = aaa\rbbb")
	//\t 制表符
	fmt.Println("制表符 = aaaaaaaaaaaaa")
	fmt.Println("制表符 = aaaaa\tbbbbb")
	fmt.Println("制表符 = aaaaaaaa\tbbbbb")
	//\" 双引号
	fmt.Println("双引号" + "\"Golang\"")

	fmt.Println()
	fmt.Println("布尔数据类型--------------------------------------------------------")

	// 布尔数据类型
	var flag01 bool = false
	fmt.Println("flag01 = ", flag01)
	var flag02 bool = true
	fmt.Println("flag02 = ", flag02)
	var flag03 bool = 5 > 9
	fmt.Println("flag03 = ", flag03)

	fmt.Println()
	fmt.Println("字符串数据类型--------------------------------------------------------")

	var s1 string = "你好全面拥抱Golang"
	fmt.Println("字符串 s1 = ", s1)
	//2.字符串是不可变的：指的是字符串一旦定义好，其中的字符的值不能改变
	var s2 string = "abc"
	s2 = "def"
	//s2[0] = 't'
	fmt.Println("字符串 s2 = ", s2)
	//3.字符串的表示形式：
	//（1）如果字符串中没有特殊字符，字符串的表示形式用双引号
	//（2）如果字符串中有特殊字符，字符串的表示形式用反引号 ``
	var s4 string = `
	package main
	import "fmt"
	func main(){
			//测试布尔类型的数值：
			var flag01 bool = true
			fmt.Println(flag01)
	
			var flag02 bool = false
			fmt.Println(flag02)
	}
	`
	fmt.Println("字符串 s4 = ", s4)
	//4.字符串的拼接效果：
	var s5 string = "abc" + "def"
	s5 += "hijk"
	fmt.Println("字符串 s5 = ", s5)

	//当一个字符串过长的时候：注意：+保留在上一行的最后
	var s6 string = "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" +
		"def" + "abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def"
	fmt.Println(s6)

	fmt.Println()
	fmt.Println("基本数据类型默认值--------------------------------------------------------")

	var ints int
	var float32s float32
	var float64s float64
	var bools bool
	var strings string
	fmt.Println("int默认值 = ", ints)
	fmt.Println("float32默认值 = ", float32s)
	fmt.Println("float64默认值 = ", float64s)
	fmt.Println("bool默认值 = ", bools)
	fmt.Println("string默认值 = ", strings)

	fmt.Println()
	fmt.Println("基本数据类型转换--------------------------------------------------------")

	//进行类型转换
	var n1 int = 100
	fmt.Println(n1)
	//var n2 float32 = n1  在这里自动转换不好使，比如显式转换
	var n2 float32 = float32(n1)
	fmt.Println(n2)
	//注意：n1的类型其实还是int类型，只是将n1的值100转为了float32而已，n1还是int的类型
	fmt.Printf("%T", n1) //int
	fmt.Println()

	//将int64转为int8的时候，编译不会出错的，但是会数据的溢出
	var n3 int64 = 888888
	var n4 int8 = int8(n3)
	fmt.Println(n4)

	var n5 int32 = 12
	var n6 int64 = int64(n5) + 30 //一定要匹配=左右的数据类型
	fmt.Println(n5)
	fmt.Println(n6)

	fmt.Println("基本数据类型转换string--------------------------------------------------------")

	var q1 int = 19
	var q2 float32 = 4.78
	var q3 bool = false
	var q4 byte = 'a'

	var q5 string = fmt.Sprintf("%d", q1)
	fmt.Printf("q1对应的类型是：%T ，s1 = %q \n", q5, q5)
	var q6 string = fmt.Sprintf("%f", q2)
	fmt.Printf("q2对应的类型是：%T ，s2 = %q \n", q6, q6)
	var q7 string = fmt.Sprintf("%t", q3)
	fmt.Printf("q7对应的类型是：%T ，s3 = %q \n", q7, q7)
	var q8 string = fmt.Sprintf("%c", q4)
	fmt.Printf("q8对应的类型是：%T ，s4 = %q \n", q8, q8)

	var q9 int = 18
	var q10 string = strconv.FormatInt(int64(q9), 10)
	//参数：第一个参数必须转为int64类型 ，第二个参数指定字面值的进制形式为十进制
	fmt.Printf("q10对应的类型是：%T ，s1 = %q \n", q10, q10)

	var q11 float64 = 4.29
	//第二个参数：'f'（-ddd.dddd）  第三个参数：9 保留小数点后面9位  第四个参数：表示这个小数是float64类型
	var q12 string = strconv.FormatFloat(q11, 'f', 9, 64)
	fmt.Printf("q12对应的类型是：%T ，s1 = %q \n", q12, q12)

	var q13 bool = true
	var q14 string = strconv.FormatBool(q13)
	fmt.Printf("q14对应的类型是：%T ，s1 = %q \n", q14, q14)

	fmt.Println("string转基本数据类型--------------------------------------------------------")
	fmt.Println()

	var w1 string = "true"
	var b bool
	//ParseBool这个函数的返回值有两个：(value bool, err error)
	//value就是我们得到的布尔类型的数据，err出现的错误
	//我们只关注得到的布尔类型的数据，err可以用_直接忽略
	b, _ = strconv.ParseBool(w1)
	fmt.Printf("b的类型是：%T,b=%v \n", b, b)

	//string---》int64
	var w2 string = "12"
	var b1 int64
	b1, _ = strconv.ParseInt(w2, 10, 64)
	fmt.Printf("b1的类型是: %T,b=%v \n", b1, b1)

	//string-->float32/float64
	var w3 string = "3.14"
	var b2 float64
	b2, _ = strconv.ParseFloat(w3, 64)
	fmt.Printf("b2的类型是: %T,b=%v \n", b2, b2)

	//注意：string向基本数据类型转换的时候，一定要确保string类型能够转成有效的数据类型，否则最后得到的结果就是按照对应类型的默认值输出
	var w4 string = "golang"
	var b3 bool
	b3, _ = strconv.ParseBool(w4)
	fmt.Printf("b1的类型是：%T,b1=%v \n", b3, b3)

	fmt.Println("复杂数据类型指针--------------------------------------------------------")
	fmt.Println()

	var age int = 18
	//&符号+变量 就可以获取这个变量内存的地址
	fmt.Println(&age)

	//定义一个指针变量：
	//var代表要声明一个变量
	//ptr 指针变量的名字
	//ptr对应的类型是：*int 是一个指针类型 （可以理解为 指向int类型的指针）
	//&age就是一个地址
	var ptr *int = &age
	fmt.Println(ptr)
	fmt.Println("ptr本身这个存储空间的地址为：", &ptr)
	//想获取ptr这个指针或者这个地址指向的那个数据：
	fmt.Printf("ptr指向的数值为：%v", *ptr) //ptr指向的数值为：18
}
